package org.testis.communication.client;

import org.testis.utils.PolledInputStream;
import java.io.PrintStream;
import org.apache.commons.net.telnet.TelnetClient;
import java.io.IOException;
import java.net.*;

/**
 * A class for handling telnet operations. 
 * Exetens apache common's telnet client
 * @author nurhat
 */
public class AtofTelnetClient extends TelnetClient {

    /**
     * Input stream of telnet client
     */
    private PolledInputStream in;
    /**
     * Output stream of telnet client
     */
    private PrintStream out;
    private String m_prompt = "#";
    private boolean m_loggedIn = false;
    private String m_user;
    private String m_password;
    private String m_server;
    private int m_port;

    /**
     * Creates telnet client for the given parameters.
     * Default port is choosen 23.
     * @param server
     * @param user
     * @param password
     */
    public AtofTelnetClient(String server,
            String user,
            String password) {
        super();
        String [] ips=server.split(" ");
        m_server = server.trim();
        m_user = user;
        m_password = password;
        m_port = 23;
        if(ips.length>1){
            m_server=ips[0];
            try{
            m_port=Integer.parseInt(ips[1]);
            }catch(Exception ex){
          
            }
        }
       
    }

    /**
     * Creates telnet client for the given parameters.
     * @param server
     * @param port
     * @param user
     * @param password
     */
    public AtofTelnetClient(String server,
            int port,
            String user,
            String password) {
        super();
        m_server = server;
        m_user = user;
        m_password = password;
        m_port = port;
    }

    /**
     * Create a connection telnet client
     * @throws java.net.SocketException
     * @throws java.io.IOException
     */
    public boolean connect() {
        try {
            setDefaultTimeout(6000);
            setConnectTimeout(6000);
            super.setServerSocketFactory(new TimeoutSockectFactory());
            super.connect(m_server,
                    m_port);
            setSoTimeout(6000);
            setSoLinger(true,
                    6000);
            in = new PolledInputStream(getInputStream(),
                    6000);
            out = new PrintStream(getOutputStream());
            return true;
        } catch (SocketException ex) {
        } catch (IOException ex) {
        }
        return false;
    }

    /**
     * Log the user on
     * @return true if successfully logged in
     * @throws java.io.IOException
     */
    public boolean login() {
        String output = readUntil("login: ");
        if (output == null) {
            return false;
        }
        write(m_user);
        output = readUntil("Password: ");
        if (output == null) {
            return false;
        }
        write(m_password);

        output = readUntil(getCommandPromptChar() + " ");
        m_loggedIn = output == null ? false : true;
        return m_loggedIn;

    }

    /**
     * Reads stdout until given pattern found
     * @param pattern
     * @return stdout output until given pattern found
     * @throws java.io.IOException
     */
    private String readUntil(
            String pattern) {
        try {

            char lastChar = pattern.charAt(pattern.length() - 1);
            StringBuffer sb = new StringBuffer();
            int charValue;
            char ch;
            while ((charValue = in.read()) != -1) {
                ch = (char) charValue;
                sb.append(ch);
                if (ch == lastChar) {
                    if (sb.toString().endsWith(pattern)) {
                        return sb.toString();
                    }
                }
            }
            return null;
        } catch (IOException ex) {
        }
        return null;
    }

    /**
     * Writes given value to stdout
     * @param value
     */
    private void write(String value) {
        out.println(value);
        out.flush();
        // System.out.println(value);
    }

    /**
     * Sends given command to telnet client
     * @param command
     * @return output of command as string. A return value with null means
     * an error occured when operating command
     * @throws java.io.IOException
     */
    public String sendCommand(
            String command) {
        StringBuilder output = new StringBuilder();
        try {
            String[] commandList = command.split("\r|\n|\r\n|" + System.getProperty("line.separator"));
            for (int i = 0; i < commandList.length; i++) {
                if (!commandList[i].isEmpty()) {
                    write(commandList[i]);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                    }
                    output.append(readUntil(getCommandPromptChar()));
                }
            }
        }catch(NullPointerException ex){
            ex.printStackTrace();
        }catch(Exception ex){
            ex.printStackTrace();
        }
        return output.toString();
    }

    /**
     * End current telnet connection
     * @throws java.io.IOException
     */
    public void endConnection() throws IOException {
        if (m_loggedIn) {
            write("logout");
            m_loggedIn =
                    false;
        }
        super.disconnect();
    }

    public String getCommandPromptChar() {
        return m_prompt;
    }

    public void setCommandPromptChar(String m_prompt) {
        this.m_prompt = m_prompt;
    }
}

